﻿namespace WPForms.Phone.ViewModel
{
    using System;
    using System.Device.Location;
    using System.Net;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Ink;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Shapes;
    using Microsoft.Practices.Prism.Commands;
    using Newtonsoft.Json;
    using Newtonsoft.Json.Linq;
    using WPForms.Common.Model;

    /// <summary>
    /// View model class for the <see cref="GeoLocation"/> model object.
    /// </summary>
    public class GeoLocationViewModel : ElementViewModelBase<GeoLocation>
    {
        /// <summary>
        /// The geocoordinate watcher
        /// </summary>
        private GeoCoordinateWatcher watcher;

        /// <summary>
        /// The current map center
        /// </summary>
        private GeoCoordinate center;

        /// <summary>
        /// Initializes a new instance of the <see cref="GeoLocationViewModel" /> class.
        /// </summary>
        /// <param name="model">The model.</param>
        public GeoLocationViewModel(GeoLocation model)
            : base(model)
        {
            this.UseCurrentCommand = new DelegateCommand(this.UseCurrent);
        }

        /// <summary>
        /// Gets the command responsible for getting the current location.
        /// </summary>
        public ICommand UseCurrentCommand { get; private set; }

        /// <summary>
        /// Gets the friendly location.
        /// </summary>
        public string Location
        {
            get
            {
                return this.Model.FriendlyLocation;
            }

            private set
            {
                this.Model.FriendlyLocation = value;
                this.RaisePropertyChanged(() => this.Location);

                // set overriden flag
                this.Model.IsLocationOverriden = true;
            }
        }

        /// <summary>
        /// Gets the center.
        /// </summary>
        public GeoCoordinate Center
        {
            get
            {
                return this.center;
            }

            private set
            {
                this.center = value;
                this.RaisePropertyChanged(() => this.Center);
            }
        }

        /// <summary>
        /// Enters the current position
        /// </summary>
        private void UseCurrent()
        {
            if (this.watcher == null)
            {
                this.watcher = new GeoCoordinateWatcher();
                this.watcher.PositionChanged += new EventHandler<GeoPositionChangedEventArgs<GeoCoordinate>>(this.Watcher_PositionChanged);
                this.watcher.Start();
            }
        }

        /// <summary>
        /// Watcher_s the position changed.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The e.</param>
        private void Watcher_PositionChanged(object sender, GeoPositionChangedEventArgs<GeoCoordinate> e)
        {
            if (!e.Position.Location.IsUnknown)
            {
                this.Model.Altitute = e.Position.Location.Altitude;
                this.Model.Latitude = e.Position.Location.Latitude;
                this.Model.Longitude = e.Position.Location.Longitude;
                this.Center = e.Position.Location;

                var key = (string)Application.Current.Resources["BingMapsKey"];
                var url = string.Format(
                    @"http://dev.virtualearth.net/REST/v1/Locations/{0},{1}?includeEntityTypes=address&key={2}",
                    e.Position.Location.Latitude,
                    e.Position.Location.Longitude,
                    key);
                var httpClient = (HttpWebRequest)HttpWebRequest.CreateHttp(url);
                httpClient.BeginGetResponse(
                    result =>
                    {
                        var response = (HttpWebResponse)httpClient.EndGetResponse(result);
                        if (response.StatusCode == HttpStatusCode.OK)
                        {
                            using (var reader = new System.IO.StreamReader(response.GetResponseStream()))
                            {
                                var location = JObject.Parse(reader.ReadToEnd());
                                try
                                {
                                    var resolvedLocation = (string)location["resourceSets"][0]["resources"][0]["name"];
                                    Deployment.Current.Dispatcher.BeginInvoke(() =>
                                    {
                                        this.Location = resolvedLocation;
                                        this.Model.IsLocationOverriden = false;
                                    });
                                }
                                catch (Exception)
                                {
                                }
                            }
                        }
                    },
                    null);
            }
        }
    }
}
